home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 December: Technology Seed / ATS Dec. '97.toast / Navigation Services SDK 1.0b1 / Examples / Sampler / Sampler ƒ / Mysprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-20  |  8.5 KB  |  436 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Mysprintf.c
  3.  
  4.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. #pragma segment AppSeg
  9.  
  10. #ifndef __MEMORY__
  11. #include <Memory.h>
  12. #endif
  13.  
  14. #ifndef __STDARG__
  15. #include <stdarg.h>
  16. #endif
  17.  
  18. #ifndef __STDLIB__
  19. #include <StdLib.h>
  20. #endif
  21.  
  22.  
  23. #ifndef __MYSPRINTF__
  24. #include "Mysprintf.h"
  25. #endif
  26.  
  27. // local prototypes
  28. void Calc_Widths(UInt32* Lwidth, UInt32 Lplace, UInt32* Rwidth, UInt32 Rplace);
  29. void PrintString(StringPtr* s, StringPtr sval, Boolean LeftJustified, UInt32 Lwidth, UInt32 Rwidth);
  30. StringPtr numToBase(StringPtr destStr, UInt8 filler, UInt32 base, UInt32 digits,UInt32 value);
  31.  
  32. #define    MaxBase        16
  33. #define    MaxIndex     32
  34.  
  35. #undef    NULL
  36. #define    NULL        0L
  37.  
  38.  
  39. // ********************************************************************************
  40. // *    Myssprintf()                                                                        *
  41. // ********************************************************************************
  42. void Mysprintf(StringPtr s, StringPtr fmt,...)
  43. {
  44.     va_list        ap;    //    points to each unnamed arg in turn
  45.     UInt8        *p, *sval;
  46.     UInt32        ival;
  47.     double        dval;
  48.     float_t        fval;
  49.     UInt32        power;
  50.     Boolean        conversion;
  51.     Boolean        Lspace,ShowVal,LeftJustified;
  52.     UInt8        c,filler;
  53.     UInt32        Lwidth,Rwidth;
  54.     UInt32        Lplace,Rplace,width;
  55.     Str255        tStr;
  56.     StringPtr    aChar;
  57.     
  58.     va_start(ap,fmt);    //    make ap point to 1st unnamed arg
  59.     conversion = false;
  60.     for (p = fmt; *p; p++)
  61.         {
  62.         if (*p != '%' && !conversion)
  63.             {
  64.             *s++ = *p;
  65.             continue;
  66.             }
  67.         if (*p == '%' && !conversion)
  68.             {
  69.             conversion = true;
  70.             p++;    //    point to conversion char
  71.             Lwidth = NULL;
  72.             Lplace = NULL;
  73.             Rwidth = NULL;
  74.             Rplace = NULL;
  75.             Lspace = true;    //    calculate Lspace 1st
  76.             ShowVal = false;
  77.             LeftJustified = false;
  78.             filler    = ' ';    //    default to blank unless otherwise specified
  79.             }
  80.         c = *p;
  81.         switch(c)
  82.             {
  83.             case '%':    //    just a % char
  84.                     *s++ = '%';
  85.                     conversion = false;
  86.                 break;
  87.             case 'd':
  88.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  89.                     ival = va_arg(ap,int);
  90.                     numToBase(tStr,filler,10,Lwidth,ival);
  91.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  92.                     conversion = false;
  93.                 break;
  94.             case 'f':
  95.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  96.                     fval = va_arg(ap, float_t);
  97.                     ival = (UInt32) fval;    //    during translation, the mantissa should be dropped
  98. //                    aChar = numToBase(tStr,filler,10,Lwidth,ival);
  99.                     aChar = numToBase(tStr,filler,10,0,ival);    //    experimenting w/ 0 width, so we get all digits
  100.                     *aChar++ = '.';    //    insert decimal point
  101.                         {
  102.                         UInt32 tindex = Rwidth;
  103.                         power = 1;
  104.                         while (tindex)
  105.                             {
  106.                             power *= 10;
  107.                             tindex--;
  108.                             }
  109.                         }
  110.                     dval = (fval-ival) * power;
  111.                     numToBase(aChar,filler,10,Rwidth,dval);
  112.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  113.                     conversion = false;
  114.                     break;
  115.             case 's':
  116.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  117.                     sval = va_arg(ap, StringPtr);
  118.                     PrintString(&s, sval, LeftJustified, Lwidth, Rwidth);
  119.                     conversion = false;
  120.                 break;
  121.             case 'o':    //    octal
  122.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  123.                     if (ShowVal)
  124.                         {
  125.                         *s++ = '0';
  126.                         }
  127.                     ival = va_arg(ap,int);
  128.                     numToBase(tStr,filler,8,Lwidth,ival);
  129.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  130.                     conversion = false;
  131.                     break;
  132.             case 'h':    //    h,     short
  133.             case 'l':    //    ell, long
  134.                 break;
  135.             case 'x':    //    hex lower
  136.             case 'X':    //    hex upper
  137.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  138.                     if (ShowVal)
  139.                         {
  140.                         if (c == 'x')
  141.                             BlockMove("0x",s,2);
  142.                         else
  143.                             BlockMove("0X",s,2);
  144.                             
  145.                         s+= 2;
  146.                         }
  147.                     ival = va_arg(ap,int);
  148.                     numToBase(tStr,filler,16,Lwidth,ival);
  149.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  150.                     conversion = false;
  151.                 break;
  152.             case 'b':    //    binary
  153.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  154.                     if (ShowVal)
  155.                         {
  156.                         BlockMove("0b",s,2);
  157.                         s+= 2;
  158.                         }
  159.                     ival = va_arg(ap,int);
  160.                     numToBase(tStr,filler,2,Lwidth,ival);
  161.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  162.                     conversion = false;
  163.                 break;
  164.             case '0':
  165.                     if (Lplace == NULL)
  166.                         filler = '0';
  167.             case '1':
  168.             case '2':
  169.             case '3':
  170.             case '4':
  171.             case '5':
  172.             case '6':
  173.             case '7':
  174.             case '8':
  175.             case '9':
  176.                 if (Lspace)
  177.                     {
  178.                     Lwidth = Lwidth << 8;
  179.                     Lplace++;
  180.                     Lwidth += c - '0';
  181.                     }
  182.                 else
  183.                     {
  184.                     Rwidth = Rwidth << 8;
  185.                     Rplace++;
  186.                     Rwidth += c - '0';
  187.                     }
  188.                 break;
  189.             case '.':
  190.                     Lspace = false;
  191.                     break;
  192.             case '#':
  193.                     ShowVal = true;
  194.                     break;
  195.             case '-':
  196.                     LeftJustified = true;
  197.                     break;
  198.             case '+':
  199.                 break;
  200.             case ' ':
  201.                 if (Lspace)
  202.                     {
  203.                     filler = ' ';
  204.                     }
  205.                 break;
  206.             case '*':
  207.                 width = va_arg(ap,int);    //    get width
  208.                 if (Lspace)
  209.                     {
  210.                     Lwidth = width;
  211.                     Lplace = NULL;
  212.                     }
  213.                 else
  214.                     {
  215.                     Rwidth = width;
  216.                     Rplace = NULL;
  217.                     }
  218.                 break;
  219.             default:
  220.                 *s++ = *p;
  221.                 break;
  222.         }
  223.     }
  224.     va_end(ap);    //    clean up when done
  225.     *s = 0;
  226. }
  227.  
  228.  
  229. // ********************************************************************************
  230. // *    Calc_Widths()
  231. // ********************************************************************************
  232. void Calc_Widths(UInt32* Lwidth,UInt32 Lplace, UInt32* Rwidth, UInt32 Rplace)
  233. {
  234.     UInt32 x,value,base;
  235.     Ptr    width;
  236.     
  237.     if (Lplace)
  238.         {
  239.         width = (Ptr) Lwidth+3;
  240.         for(x=0,value=0,base=1;x<Lplace;x++)
  241.             {
  242.             value += (*width) * base;
  243.             base *= 10;
  244.             width--;
  245.             }
  246.         *Lwidth = value;
  247.         }
  248.  
  249.     if (Rplace)
  250.         {
  251.         width = (Ptr) Rwidth+3;
  252.         for(x=0,value=0,base=1;x<Rplace;x++)
  253.             {
  254.             value += (*width) * base;
  255.             base *= 10;
  256.             width--;
  257.             }
  258.         *Rwidth = value;
  259.         }    
  260. }
  261.  
  262.  
  263. // ********************************************************************************
  264. // *    Calc_Widths()
  265. // *
  266. // *    PrintString
  267. // *
  268. // *    if (LeftJustified)
  269. // *        "|xxxxx      |"
  270. // *    else
  271. // *        "|      xxxxx|"
  272. // *
  273. // *    Lwidth = min # of chars
  274. // *    Rwidth = max # of chars
  275. // ********************************************************************************
  276. void PrintString(StringPtr* str, StringPtr sval, Boolean LeftJustified, UInt32 Lwidth, UInt32 Rwidth)
  277. {
  278.     StringPtr    s = *str;
  279.     UInt32        valid;
  280.     UInt32        validR = NULL;
  281.     
  282.     valid = Lwidth;
  283.     if (!valid)
  284.         valid = 255;    //    if NULL, default to max
  285.     
  286.     if (LeftJustified)
  287.     {    //
  288.         //    output data 1st, then fill
  289.         //
  290.         if (Rwidth)
  291.         {
  292.             validR = Rwidth;
  293.         }
  294.         else
  295.         {
  296.             validR = valid;
  297.         }
  298.         
  299.         while (validR && *sval)
  300.         {
  301.             *s++ = *sval;
  302.             validR--;
  303.             valid--;
  304.             sval++;
  305.         }
  306.  
  307.         while (valid)
  308.         {    //
  309.             //    we need to fill in the rest
  310.             //
  311.             *s++ = ' ';
  312.             valid--;
  313.         }
  314.     }
  315.     else
  316.     {    //
  317.         //    output filler 1st
  318.         //
  319.         if (Rwidth)
  320.         {
  321.             validR = valid - Rwidth;
  322.         }
  323.         else
  324.         {
  325.             valid = 255;    //    max allowed
  326.         }
  327.         
  328.         while (validR)
  329.         {    //
  330.             //    we need to fill in the rest
  331.             //
  332.             *s++ = ' ';
  333.             validR--;
  334.             valid--;
  335.         }
  336.  
  337.         //
  338.         //    output data 2nd
  339.         //
  340.         while (*sval && valid)
  341.         {
  342.             *s++ = *sval;
  343.             valid--;
  344.             sval++;
  345.         }
  346.     }
  347.     
  348.     *str = s;
  349. }
  350.  
  351.  
  352. // ********************************************************************************
  353. // *    StringPtr    numToBase     (Ptr destStr, char filler, int base, int digits, unsigned int value)
  354. // *    inputs:
  355. // *            destStr    :    destination string
  356. // *            filler    :    leading space filler, usually '0'
  357. // *            base    :    conversion base, 2=binary,8=octal,10=decimal,16=hex
  358. // *            digits    :    # of digits to display
  359. // *            value    :    number to convert
  360. // *    output:
  361. // *            the cstring representation of value will be moved to the location pointed to by "destStr"
  362. // *            return ptr to last char we store a null to
  363. // ********************************************************************************
  364. StringPtr numToBase(StringPtr destStr, UInt8 filler, UInt32 base, UInt32 digits, UInt32 value)
  365. {
  366.     UInt8    hex[16];
  367.     UInt8    tStr[MaxIndex+1];
  368.     UInt8*    aStr;
  369.     UInt32    index,lastIndex;
  370.     UInt8    digit,sign;
  371.  
  372.     // init hex array
  373.     for (index = 0, digit = '0'; index < 16; )
  374.         {
  375.         hex[index] = digit;
  376.         digit++;
  377.         index++;
  378.         if (index == 10)
  379.             digit = 'A';
  380.         }
  381.  
  382.     sign = 0;
  383.     if (base == 10)    //    special decimal handling
  384.         {
  385.         if (value &0x80000000)
  386.             {
  387.             value = abs(value);
  388.             sign = '-';    // automatically insert the '-' value
  389.             }
  390.         }
  391.     index = MaxIndex-1;
  392.     tStr[MaxIndex] = 0;    //    terminate string
  393.  
  394.     do     {
  395.         digit = (value % base) & 0x0F;    
  396.         tStr[index] = hex[digit];
  397.         value -= digit;
  398.         if (value)
  399.             {
  400.             value /= base;
  401.             }
  402.         index--;
  403.         }
  404.     while (value);
  405.     
  406.     if (sign)
  407.         {
  408.         tStr[index] = sign;
  409.         index--;
  410.         }
  411.     lastIndex = index+1;
  412.     
  413.     while(index!=-1)
  414.         {
  415.         tStr[index] = filler;
  416.         index--;
  417.         }
  418.     if (digits)
  419.         {
  420.         aStr = tStr + (MaxIndex-digits);
  421.         }
  422.     else
  423.         {
  424.         aStr = tStr+lastIndex;
  425.         }
  426.     
  427.     do    {
  428.         *destStr++ = *aStr++;    //    copy aStr to destStr
  429.         }
  430.     while (*aStr);
  431.     
  432.     *destStr = 0;                //    make sure we terminate the destination
  433.     
  434.     return (destStr);
  435. }
  436.